/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.oai.metadataRepository.sysnoSignatureMapping;

import cz.mzk.oai.metadataRepository.metadata.MetadataFormat;
import cz.mzk.oai.metadataRepository.repository.Identifier;
import cz.mzk.oai.metadataRepository.repository.collections.MetadataCollection;
import cz.mzk.oai.metadataRepository.repository.records.Record;
import cz.mzk.oai.metadataRepository.repository.records.presentAndDeleted.PresentRecord;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.XPath;

/**
 *
 * @author Martin Řehánek (rehan at mzk.cz)
 */
public class RepositoryMappingsLoader implements MappingsLoader {

    private static final Logger logger = Logger.getLogger(RepositoryMappingsLoader.class.getName());
    private final XPath signatureXpath = DocumentHelper.createXPath("/marc21:record/marc21:datafield[@tag=910]/marc21:subfield[@code='b']");
    private final List<MetadataCollection> collections;
    private final List<Mapping> mappings = new ArrayList<Mapping>();

    public RepositoryMappingsLoader(List<MetadataCollection> collections) {
        this.collections = collections;
        initNamespace();
    }

    private void initNamespace() {
        Map<String, String> prefixNamespaceMap = new HashMap<String, String>();
        prefixNamespaceMap.put("marc21", "http://www.loc.gov/MARC21/slim");
        signatureXpath.setNamespaceURIs(prefixNamespaceMap);
    }

    public List<Mapping> loadMappings() {
        loadMappingsFromRepository();
        return mappings;
    }

    private void loadMappingsFromRepository() {
        for (MetadataCollection collection : collections) {
            logger.log(Level.INFO, "Processing collection {0}", collection.getName());
            loadMappingsFromCollection(collection);
        }
    }

    private void loadMappingsFromCollection(MetadataCollection collection) {
        List<Record> records = collection.getRecords(MetadataFormat.marc21, null, null);
        for (Record record : records) {
            try {
                loadMapping(record);
            } catch (IOException ex) {
                Logger.getLogger(RepositoryMappingsLoader.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void loadMapping(Record record) throws IOException {
        if (!record.isDeleted()) {
            logger.log(Level.FINE, "Loading record {0}:{1}", new Object[]{record.getId().getBase(), record.getId().getSysno()});
//            System.out.println("sysno: " + record.getId().getSysno());
//            System.out.println("baze: " + record.getId().getBase().toString());
            Document doc = ((PresentRecord) record).getMetadata();
            addMappingIfFound(doc, record.getId());
        }
    }

    private void addMappingIfFound(Document doc, Identifier id) {
        Element subfieldEl = (Element) signatureXpath.selectSingleNode(doc);
        if (subfieldEl != null) {
            String signature = subfieldEl.getTextTrim();
            if (signature == null || "".equals(signature)) {
                logger.log(Level.WARNING, "record {0} has no signature", id.toString());
            } else {
//                System.out.println("signature: " + signature);
                addMapping(id, signature);
            }
        } else {
            logger.log(Level.WARNING, "record {0} has no signature", id.toString());
        }
    }

    private void addMapping(Identifier id, String signature) {
        Mapping mapping = new Mapping(id, signature);
        mappings.add(mapping);
    }
}
